#include "border_tracing.h"

#define COLOR_WHITE 255

// fiind data o imagine aceasta functie extrage conturul
// returneaza true daca reuseste
bool contour_extract(Contour &contour, unsigned int width, 
					 unsigned int height, int wide, const BYTE *bitmap)
{
	unsigned int x, y;
	bool is_first, is_finished, is_closed;
	unsigned char dir, dir_start, dir_next;
	Point first, second, next, current;

	// cauta primul pixel diferit de zero
	is_finished = false;
	for (y = 0; y < height && !is_finished; y++)
		for (x = 0; x < width && !is_finished; x++)
			if (bitmap[y * wide + x] != COLOR_WHITE)
			{
				current.first  = x;
				current.second = y;
				is_finished = true;
			}

	if (!is_finished) return false;

	contour.push_back(current);
	first = current;

	dir = 7;
	is_first = true;
	is_finished = false;

	while (!is_finished)
	{
		// determinam noua directie de cautare
		if (dir % 2 == 0)
			dir_start = (dir + 7) % 8;
		else
			dir_start = (dir + 6) % 8;

		// incepem cautarea
		is_closed = false;
		for (int k = 0; k < 8; k++)
		{
			// calculam valoarea urmatorului punct
			dir_next = (dir_start + k) % 8;
			next = point_next(current, dir_next);

			// ne asiguram ca suntem in imagine
			if (next.second >= height || next.second < 0) continue;
			if (next.first  >= width  || next.first  < 0) continue;

			// testam daca pixelul indicat de punct e pixel obiect
			if (bitmap[next.second * wide + next.first] != COLOR_WHITE)
			{		
				if (is_first)
				{
					// salvam al doilea pixel
					is_first = false;
					second = next;
				}
				// testam sa vedem daca alg sa incheiat
				else if ((first == current) && (second == next))
				{
					contour.pop_back(); // stergm ultimul element
					is_finished = true;
				}

				if (!is_finished)
				{
					// adaugam punctul
					dir = dir_next;
					current = next;
					contour.push_back(current);
					is_closed = true;
				}

				break;
			}
		}

		// daca nu a fost gasit nici un pixel obiect atunci returnam
		if (!is_closed) break;
	}

	return is_finished;
}